package gw.com.android.presenter;

import android.text.TextUtils;

import org.json.JSONObject;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Map;
import java.util.Properties;

import gw.com.android.app.AppMain;
import gw.com.android.app.GTConfig;
import gw.com.android.model.ConfigType;
import gw.com.android.model.ConfigUtil;
import gw.com.android.presenter.http.Https;
import gw.com.android.utils.ThreadPool;
import okhttp3.Call;
import okhttp3.Request;
import okhttp3.Response;
import www.com.library.app.Logger;

/**
 * 启动页更新类
 * <p>
 * 缓存文件目录
 * data/data/${packageName}/files/launchPage/page.data
 * data/data/${packageName}/files/launchPage/${id}_${version}/${imageName}
 *
 * @author jett
 * @since 2017-09-04.
 */
@SuppressWarnings("ResultOfMethodCallIgnored")
public class LaunchPagePresenter {

    private static final String TAG = "LaunchPagePresenter";

    static void preload() {
        Logger.i(TAG, "preload .. ");
        ThreadPool.getInstance().execute(new Runnable() {
            @Override
            public void run() {
                loadLaunchPage();
            }
        });
    }

    private static void loadLaunchPage() {
        Logger.i(TAG, "loadLaunchPage .. ");
        JSONObject jsonObject = ConfigUtil.instance().mConfigObject.optJSONObject(ConfigType.LAUNCH_PAGE_TAG);
        boolean enable = jsonObject == null || jsonObject.optBoolean(ConfigType.CONFIG_TYPE_HAS_NEED_TAG);
        if (!enable) {
            Logger.i(TAG, "launch page is disable.");
            return;
        }
        Page page = parseLaunchAds();
        downloadImage(page);
    }

    /**
     * 获取启动页配置
     */
    public static Page fetch() {
        File file = getPageDataFile();
        return Page.fromFile(file);
    }

    private static Page parseLaunchAds() {
        Logger.i(TAG, "parseLaunchAds .. ");
        Map<String, AdsData> guestAds = AdsConfigPresenter.getInstance().getAllAds(GTConfig.ACC_TYPE_GUEST);
        Map<String, AdsData> demoAds = AdsConfigPresenter.getInstance().getAllAds(GTConfig.ACC_TYPE_DEMO);
        Map<String, AdsData> realAds = AdsConfigPresenter.getInstance().getAllAds(GTConfig.ACC_TYPE_REAL);

        Page demo = parseByUserType(demoAds);
        Page guest = parseByUserType(guestAds);
        Page real = parseByUserType(realAds);
        return compare(demo, guest, real);
    }

    private static Page compare(Page... datas) {
        if (datas != null && datas.length > 0) {
            Arrays.sort(datas, new Comparator<Page>() {
                @Override
                public int compare(Page lhs, Page rhs) {
                    if (lhs == null) {
                        return 1;
                    }
                    if (rhs == null) {
                        return -1;
                    }
                    int version = rhs.version.compareTo(lhs.version);
                    return version == 0 ? rhs.id.compareTo(lhs.id) : version;
                }
            });
            return datas[0];
        }
        return null;
    }

    private static Page parseByUserType(Map<String, AdsData> ads) {
        if (ads != null) {
            AdsData launchAd = ads.get(AdsConfigPresenter.TYPE_LAUNCH_PAGE);
            if (launchAd != null && launchAd.adPics != null && !launchAd.adPics.isEmpty()) {
                AdsData.PicData picData = launchAd.adPics.get(0);
                Page page = new Page();
                page.id = launchAd.id;
                page.version = launchAd.version;
                if (TextUtils.isEmpty(page.id) || TextUtils.isEmpty(page.version)) {
                    return null;
                }
                page.imageUrl = picData.url;
                if (TextUtils.isEmpty(page.imageUrl)) {
                    return null;
                }
                page.imageId = picData.id;
                page.linkUrl = picData.link;
                page.title = picData.title;
            }
        }
        return null;
    }

    private static void downloadImage(Page page) {
        Logger.i(TAG, "download launch page .. ");
        if (page == null || TextUtils.isEmpty(page.id) || TextUtils.isEmpty(page.imageUrl)) {
            Logger.i(TAG, "page data is null or data is imcompletion");
            deletePageDataFile();
            return;
        }
        Page fetch = fetch();
        if (fetch != null) {
            String version = page.version == null ? "" : page.version;
            if (page.id.equals(fetch.id) && version.equals(fetch.version)) {
                Logger.i(TAG, "this page is already downloaded. id = " + page.id + " version = " + page.version);
                return;
            }

        }
        File imageFile = page.getImageFile();
        if (!imageFile.exists()) {
            File parent = imageFile.getParentFile();
            if (!parent.exists()) {
                parent.mkdirs();
            }
            try {
                imageFile.createNewFile();
            } catch (IOException e) {
                Logger.e(TAG, e);
            }
        }
        downloadImageUncheck(page, imageFile);
    }

    private static void downloadImageUncheck(Page page, File outFile) {
        Logger.i(TAG, "acquite new launch page.");
        FileOutputStream out = null;
        Request request = new Request.Builder().url(page.imageUrl).build();
        Call call = new Https().getOkHttpClient().newCall(request);
        try {
            Response response = call.execute();
            if (response.code() < 200 || response.code() >= 300) {
                Logger.i(TAG, "response code error. code = " + response.code());
                return;
            }
            InputStream in = response.body().byteStream();
            out = new FileOutputStream(outFile);
            int len;
            byte[] buff = new byte[2048];
            while ((len = in.read(buff)) != -1) {
                out.write(buff, 0, len);
            }
            out.flush();
        } catch (IOException e) {
            Logger.e(TAG, e);
            return;
        } finally {
            if (out != null) {
                try {
                    out.close();
                } catch (IOException ignore) {
                }
            }
        }
        Logger.i(TAG, "acquire new launch page successful");
        Page.store2File(page);
        dumpDir(page);
    }

    private static void deletePageDataFile() {
        File file = getPageDataFile();
        if (file.exists()) {
            file.delete();
        }
        dumpDir(null);
    }

    private static File getPageDir() {
        File dir = AppMain.getApp().getFilesDir();
        File file = new File(dir, "launchPage");
        if (!file.exists()) {
            if (!file.mkdirs()) {
                Logger.i("", "");
            }
        }
        return file;
    }

    private static File getPageDataFile() {
        File dir = getPageDir();
        return new File(dir, "page.data");
    }

    /**
     * 清除缓存文件
     */
    private static void dumpDir(Page data) {
        File pageDir = getPageDir();
        if (pageDir != null && pageDir.isDirectory()) {
            File[] files = pageDir.listFiles();
            if (files != null && files.length > 0) {
                for (File file : files) {
                    if (file != null && file.isDirectory()) {
                        if (data == null || !file.getPath().equals(data.getImageDir())) {
                            delete(file);
                        }
                    }
                }
            }
        }
    }

    private static void delete(File file) {
        File[] files = file.listFiles();
        if (files != null && files.length > 0) {
            for (File f : files) {
                f.delete();
            }
        }
        file.delete();
    }

    public static class Page {
        String id;
        String imageId;
        String linkUrl;
        String title;
        String imageUrl;
        String version;

        public File getImageFile() {
            if (TextUtils.isEmpty(imageUrl)) {
                return null;
            }
            int index = imageUrl.lastIndexOf("/");
            String name;
            if (index < 0) {
                name = "default.png";
            } else {
                name = imageUrl.substring(index, imageUrl.length());
            }
            String imageDir = getImageDir();
            return new File(imageDir, name);
        }

        String getImageDir() {
            File pageDir = getPageDir();
            return pageDir.getAbsolutePath() + File.separator + id + "_" + version;
        }

        static Page fromFile(File file) {
            if (file != null && file.exists()) {
                try {
                    FileInputStream in = new FileInputStream(file);
                    Properties properties = new Properties();
                    properties.load(in);
                    Page data = new Page();
                    data.id = properties.getProperty("id");
                    data.imageId = properties.getProperty("imageId");
                    data.linkUrl = properties.getProperty("linkUrl");
                    data.title = properties.getProperty("title");
                    data.imageUrl = properties.getProperty("imageUrl");
                    data.version = properties.getProperty("version");
                    return data;
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
            return null;
        }

        static void store2File(Page data) {
            Properties properties = new Properties();
            properties.setProperty("id", data.id);
            properties.setProperty("imageId", data.imageId);
            properties.setProperty("linkUrl", data.linkUrl);
            properties.setProperty("title", data.title);
            properties.setProperty("imageUrl", data.imageUrl);
            properties.setProperty("version", data.version);
            File file = getPageDataFile();
            if (file.exists()) {
                file.delete();
            }
            try {
                FileOutputStream out = new FileOutputStream(file);
                properties.store(out, "launch page info");
            } catch (Exception e) {
                Logger.e(TAG, e);
            }
        }

    }

}
